package com.whfc.common.obd;

import com.google.common.base.Preconditions;
import com.whfc.common.util.ByteUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.whfc.common.obd.ObdConst.*;

/**
 * @Description: OBD数据解析工具类
 * @author: xugcheng
 * @version: 1.0
 * @date: 2020-10-19 9:46
 */
public class ObdDataUtil {

    private static Logger logger = LoggerFactory.getLogger(ObdDataUtil.class);

    public static final int ID_101 = 0x0101;

    public static final int ID_111 = 0x0111;
    public static final int ID_112 = 0x0112;
    public static final int ID_113 = 0x0113;
    public static final int ID_114 = 0x0114;
    public static final int ID_115 = 0x0115;
    public static final int ID_116 = 0x0116;
    public static final int ID_120 = 0x0120;
    public static final int ID_121 = 0x0121;

    public static final int ID_131 = 0x0131;
    public static final int ID_132 = 0x0132;
    public static final int ID_133 = 0x0133;
    public static final int ID_134 = 0x0134;
    public static final int ID_135 = 0x0135;
    public static final int ID_136 = 0x0136;

    public static final int ID_151 = 0x0151;
    public static final int ID_152 = 0x0152;
    public static final int ID_153 = 0x0153;

    public static final int ID_0CF00400 = 0x0CF00400;
    public static final int ID_0CF00300 = 0x0CF00300;
    public static final int ID_18FEDF00 = 0x18FEDF00;
    public static final int ID_18FEF500 = 0x18FEF500;
    public static final int ID_18FEF100 = 0x18FEF100;
    public static final int ID_18ECFF00 = 0x18ECFF00;
    public static final int ID_18EBFF00 = 0x18EBFF00;
    public static final int ID_18FEEE00 = 0x18FEEE00;
    public static final int ID_18FEF200 = 0x18FEF200;
    public static final int ID_18FEEF00 = 0x18FEEF00;
    public static final int ID_18FEE900 = 0x18FEE900;
    public static final int ID_18FECA00 = 0x18FECA00;
    public static final int ID_18FEF600 = 0x18FEF600;
    public static final int ID_18FEF700 = 0x18FEF700;
    public static final int ID_18FEE500 = 0x18FEE500;
    public static final int ID_18FEE400 = 0x18FEE400;
    public static final int ID_18FEBD00 = 0x18FEBD00;
    public static final int ID_18FEE000 = 0x18FEE000;
    public static final int ID_18FF0800 = 0x18FF0800;
    public static final int ID_18FEFF00 = 0x18FEFF00;

    public static final int ID_18F0010B = 0x18F0010B;
    public static final int ID_0CF00203 = 0x0CF00203;
    public static final int ID_18F00503 = 0x18F00503;
    public static final int ID_18FE4A03 = 0x18FE4A03;
    public static final int ID_18FEF121 = 0x18FEF121;
    public static final int ID_0CFE6CEE = 0x0CFE6CEE;
    public static final int ID_0C00000B = 0x0C00000B;
    public static final int ID_0C000F0B = 0x0C000F0B;
    public static final int ID_0C000024 = 0x0C000024;
    public static final int ID_0C000003 = 0x0C000003;
    public static final int ID_0C000F03 = 0x0C000F03;
    public static final int ID_0C000021 = 0x0C000021;
    public static final int ID_0C000F21 = 0x0C000F21;
    public static final int ID_0CFF0431 = 0x0CFF0431;
    public static final int ID_18E00021 = 0x18E00021;


    /**
     * 发动机扭矩模式
     */
    private static final String[] ENGINE_TORQUE_MODE = new String[]{
            "低速空转调速器输出/无请求（默认模式）",
            "加速踏板/操作者选择",
            "巡游控制",
            "PTO 调速器",
            "道路速度调速器",
            "ASR 控制",
            "传动系统控制",
            "ABS 控制",
            "转矩限制",
            "高速调速器",
            "刹车系统",
            "遥控加速器",
            "未定义",
            "未定义",
            "其他",
            "不可用"
    };

    /**
     * 故障诊断码分包1
     */
    public static int DTC_PACKET_1 = 0x01;

    /**
     * 故障诊断码分包2
     */
    public static int DTC_PACKET_2 = 0x02;

    /**
     * 故障诊断码分包3
     */
    public static int DTC_PACKET_3 = 0x03;

    /**
     * 判断是否有效数据帧
     *
     * @param frameId
     * @return
     */
    public static boolean isValidFrameId(long frameId) {
//        for (int id : FRAME_ID_ARR) {
//            if (id == frameId) {
//                return true;
//            }
//        }
//        return false;
        //判断frameId是否大于0,避免丢失未解析的数据帧
        return frameId > 0;
    }

    /**
     * 获取数据值的描述
     *
     * @param frameId
     * @param key
     * @return
     */
    private static String getValue(String frameId, int key) {
        try {
            if (ObdConst.map.containsKey(frameId)) {
                String[] value = ObdConst.map.get(frameId);
                return value[key];
            }
        } catch (Exception e) {
            logger.warn("OBD数据转换错误,{},{}", frameId, key);
        }
        return null;
    }

    /**
     * 转换数据帧(string->int[])
     *
     * @param frameData
     * @return 整形数组
     */
    public static int[] translateFrameData(String frameData) {
        boolean isOdd = frameData.length() % 2 != 0;
        int len = frameData.length() / 2 + (isOdd ? 1 : 0);
        int[] arr = new int[len];
        int startIndex = 0;
        int endIndex = 0;
        for (int i = 0; i < arr.length; i++) {
            startIndex = endIndex;
            endIndex = (i == 0 && isOdd) ? startIndex + 1 : startIndex + 2;
            String str = frameData.substring(startIndex, endIndex);
            arr[i] = Integer.parseInt(str, 16);
        }
        return arr;
    }

    /**
     * 转换数据帧(int[]->string)
     *
     * @param frameData
     * @return
     */
    public static String translateFrameData(int[] frameData) {
        return ByteUtil.toHexString(frameData);
    }

    /**
     * 解析数据帧
     *
     * @param frameIdHex
     * @param frameData
     * @return
     */
    public static ObdFrame parseObdFrame(String frameIdHex, String frameData) {
        long frameId = ByteUtil.fromHexString(frameIdHex);
        return parseObdFrame(frameId, translateFrameData(frameData));
    }

    /**
     * 解析数据帧
     *
     * @param frameId
     * @param frameData
     * @return
     */
    public static ObdFrame parseObdFrame(long frameId, String frameData) {
        return parseObdFrame(frameId, translateFrameData(frameData));
    }

    /**
     * 解析数据帧
     *
     * @param frameId
     * @param frameData
     * @return
     */
    public static ObdFrame parseObdFrame(long frameId, int[] frameData) {
        List<ObdFrameItem> frameItemList = parseObdData(frameId, frameData);
        ObdFrame frame = new ObdFrame();
        frame.setFrameId(frameId);
        frame.setFrameIdHex(ByteUtil.toHexString((int) frameId));
        frame.setFrameData(ByteUtil.toHexString(frameData));
        frame.setFrameDataItemList(frameItemList);
        return frame;
    }

    /**
     * 解析数据(DM1/DM2 PACK,frameId=0x18EBFF00)
     *
     * @param frameDataList 分包数据帧列表
     * @return
     */
    public static ObdFrame parseObdFrame18EBFF00(List<String> frameDataList) {

        List<ObdFrameItem> itemList = new ArrayList<>(10);
        if (frameDataList != null) {
            if (frameDataList.size() > 0 && StringUtils.isNotBlank(frameDataList.get(0))) {
                int[] packet1 = translateFrameData(frameDataList.get(0));
                ObdDtc dtc1 = parseObdDtc(packet1[3], packet1[4], packet1[5], packet1[6]);
                ObdFrameItem itemDl = new ObdFrameItem("diagnostic_lamp", "诊断灯", packet1[1], "");
                ObdFrameItem itemDtc1 = new ObdFrameItem("dtc", "诊断故障代码1", dtc1, "");
                itemList.add(itemDl);
                itemList.add(itemDtc1);
                if (frameDataList.size() > 1 && StringUtils.isNotBlank(frameDataList.get(1))) {
                    int[] packet2 = translateFrameData(frameDataList.get(1));
                    ObdDtc dtc2 = parseObdDtc(packet1[7], packet2[1], packet2[2], packet2[3]);
                    ObdDtc dtc3 = parseObdDtc(packet2[4], packet2[5], packet2[6], packet2[7]);
                    ObdFrameItem itemDtc2 = new ObdFrameItem("dtc", "诊断故障代码2", dtc2, "");
                    ObdFrameItem itemDtc3 = new ObdFrameItem("dtc", "诊断故障代码3", dtc3, "");
                    itemList.add(itemDtc2);
                    itemList.add(itemDtc3);
                    if (frameDataList.size() > 2 && StringUtils.isNotBlank(frameDataList.get(2))) {
                        int[] packet3 = translateFrameData(frameDataList.get(2));
                        ObdDtc dtc4 = parseObdDtc(packet3[1], packet3[2], packet3[3], packet3[4]);
                        ObdFrameItem itemDtc4 = new ObdFrameItem("dtc", "诊断故障代码4", dtc4, "");
                        itemList.add(itemDtc4);
                        if (frameDataList.size() > 3 && StringUtils.isNotBlank(frameDataList.get(3))) {
                            int[] packet4 = translateFrameData(frameDataList.get(3));
                            ObdDtc dtc5 = parseObdDtc(packet3[5], packet3[6], packet3[7], packet4[1]);
                            ObdDtc dtc6 = parseObdDtc(packet4[2], packet4[3], packet4[4], packet4[5]);
                            ObdFrameItem itemDtc5 = new ObdFrameItem("dtc", "诊断故障代码5", dtc5, "");
                            ObdFrameItem itemDtc6 = new ObdFrameItem("dtc", "诊断故障代码6", dtc6, "");
                            itemList.add(itemDtc5);
                            itemList.add(itemDtc6);
                            if (frameDataList.size() > 4 && StringUtils.isNotBlank(frameDataList.get(4))) {
                                int[] packet5 = translateFrameData(frameDataList.get(4));
                                ObdDtc dtc7 = parseObdDtc(packet4[6], packet4[7], packet5[1], packet5[2]);
                                ObdDtc dtc8 = parseObdDtc(packet5[3], packet5[4], packet5[5], packet5[6]);
                                ObdFrameItem itemDtc7 = new ObdFrameItem("dtc", "诊断故障代码7", dtc7, "");
                                ObdFrameItem itemDtc8 = new ObdFrameItem("dtc", "诊断故障代码8", dtc8, "");
                                itemList.add(itemDtc7);
                                itemList.add(itemDtc8);
                            }
                        }
                    }
                }
            }
        }

        ObdFrame frame = new ObdFrame();
        frame.setFrameId((long) ID_18EBFF00);
        frame.setFrameIdHex(ByteUtil.toHexString(ID_18EBFF00));
        frame.setFrameData(StringUtils.join(frameDataList));
        frame.setFrameDataItemList(itemList);
        return frame;
    }

    /**
     * 解析OBD数据项
     *
     * @param frameIdHex
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData(String frameIdHex, String frameData) {
        long frameId = ByteUtil.fromHexString(frameIdHex);
        return parseObdData(frameId, translateFrameData(frameData));
    }

    /**
     * 解析OBD数据项
     *
     * @param frameId
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData(long frameId, String frameData) {
        return parseObdData(frameId, translateFrameData(frameData));
    }

    /**
     * 解析OBD数据项
     *
     * @param frameId   数据帧ID
     * @param frameData 数据帧数组
     * @return
     */
    public static List<ObdFrameItem> parseObdData(long frameId, int[] frameData) {
        int id = (int) frameId;
        List<ObdFrameItem> obdData = new ArrayList<>();
        switch (id) {
            case ID_101:
                obdData = parseObdData101(frameData);
                break;
            case ID_111:
                obdData = parseObdData111(frameData);
                break;
            case ID_112:
                obdData = parseObdData112(frameData);
                break;
            case ID_113:
                obdData = parseObdData113(frameData);
                break;
            case ID_114:
                obdData = parseObdData114(frameData);
                break;
            case ID_115:
                obdData = parseObdData115(frameData);
                break;
            case ID_116:
                obdData = parseObdData116(frameData);
                break;
            case ID_120:
                obdData = parseObdData120(frameData);
                break;
            case ID_121:
                obdData = parseObdData121(frameData);
                break;
            case ID_131:
                obdData = parseObdData131(frameData);
                break;
            case ID_132:
                obdData = parseObdData132(frameData);
                break;
            case ID_133:
                obdData = parseObdData133(frameData);
                break;
            case ID_134:
                obdData = parseObdData134(frameData);
                break;
            case ID_135:
                obdData = parseObdData135(frameData);
                break;
            case ID_136:
                obdData = parseObdData136(frameData);
                break;
            case ID_151:
                obdData = parseObdData151(frameData);
                break;
            case ID_152:
                obdData = parseObdData152(frameData);
                break;
            case ID_153:
                obdData = parseObdData153(frameData);
                break;
            case ID_0CF00400:
                obdData = parseObdData0CF00400(frameData);
                break;
            case ID_0CF00300:
                obdData = parseObdData0CF00300(frameData);
                break;
            case ID_18FEDF00:
                obdData = parseObdData18FEDF00(frameData);
                break;
            case ID_18FEF500:
                obdData = parseObdData18FEF500(frameData);
                break;
            case ID_18FEF100:
                obdData = parseObdData18FEF100(frameData);
                break;
            case ID_18ECFF00:
                obdData = parseObdData18ECFF00(frameData);
                break;
            case ID_18EBFF00:
                obdData = parseObdData18EBFF00(frameData);
                break;
            case ID_18FEEE00:
                obdData = parseObdData18FEEE00(frameData);
                break;
            case ID_18FEF200:
                obdData = parseObdData18FEF200(frameData);
                break;
            case ID_18FEEF00:
                obdData = parseObdData18FEEF00(frameData);
                break;
            case ID_18FEE900:
                obdData = parseObdData18FEE900(frameData);
                break;
            case ID_18FECA00:
                obdData = parseObdData18FECA00(frameData);
                break;
            case ID_18FEF600:
                obdData = parseObdData18FEF600(frameData);
                break;
            case ID_18FEF700:
                obdData = parseObdData18FEF700(frameData);
                break;
            case ID_18FEE500:
                obdData = parseObdData18FEE500(frameData);
                break;
            case ID_18FEE400:
                obdData = parseObdData18FEE400(frameData);
                break;
            case ID_18FEBD00:
                obdData = parseObdData18FEBD00(frameData);
                break;
            case ID_18FEE000:
                obdData = parseObdData18FEE000(frameData);
                break;
            case ID_18FF0800:
                obdData = parseObdData18FF0800(frameData);
                break;
            case ID_18FEFF00:
                obdData = parseObdData18FEFF00(frameData);
                break;
            case ID_18F0010B:
                obdData = parseObdData18F0010B(frameData);
                break;
            case ID_0CF00203:
                obdData = parseObdData0CF00203(frameData);
                break;
            case ID_18F00503:
                obdData = parseObdData18F00503(frameData);
                break;
            case ID_18FE4A03:
                obdData = parseObdData18FE4A03(frameData);
                break;
            case ID_18FEF121:
                obdData = parseObdData18FEF121(frameData);
                break;
            case ID_0CFE6CEE:
                obdData = parseObdData0CFE6CEE(frameData);
                break;
            case ID_0C00000B:
                obdData = parseObdData0C00000B(frameData);
                break;
            case ID_0C000F0B:
                obdData = parseObdData0C000F0B(frameData);
                break;
            case ID_0C000024:
                obdData = parseObdData0C000024(frameData);
                break;
            case ID_0C000003:
                obdData = parseObdData0C000003(frameData);
                break;
            case ID_0C000021:
                obdData = parseObdData0C000021(frameData);
                break;
            case ID_0C000F21:
                obdData = parseObdData0C000F21(frameData);
                break;
            case ID_0CFF0431:
                obdData = parseObdData0CFF0431(frameData);
                break;
            case ID_18E00021:
                obdData = parseObdData18E00021(frameData);
                break;
            default:
                break;
        }
        return obdData;
    }

    /**
     * 解析数据(frameId=0x0101)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData101(int[] frameData) {

        List<ObdFrameItem> dataList = new ArrayList<>(64);
        for (int i = 0; i < frameData.length; i++) {
            int data = frameData[i];
            int bit0 = ByteUtil.getBit(data, 0);
            int bit1 = ByteUtil.getBit(data, 1);
            int bit2 = ByteUtil.getBit(data, 2);
            int bit3 = ByteUtil.getBit(data, 3);
            int bit4 = ByteUtil.getBit(data, 4);
            int bit5 = ByteUtil.getBit(data, 5);
            int bit6 = ByteUtil.getBit(data, 6);
            int bit7 = ByteUtil.getBit(data, 7);
            //0字节
            if (i == 0) {
                dataList.add(new ObdFrameItem("Brake1", "1轮制动", bit0, getValue("0x0101_1", bit0)));
                dataList.add(new ObdFrameItem("Brake2", "2轮制动", bit1, getValue("0x0101_1", bit1)));
                dataList.add(new ObdFrameItem("Brake3", "3轮制动", bit2, getValue("0x0101_1", bit2)));
                dataList.add(new ObdFrameItem("Brake4", "4轮制动", bit3, getValue("0x0101_1", bit3)));
                dataList.add(new ObdFrameItem("Work_select1", "1轮工况", bit4, getValue("0x0101_2", bit4)));
                dataList.add(new ObdFrameItem("Work_select2", "2轮工况", bit5, getValue("0x0101_2", bit5)));
                dataList.add(new ObdFrameItem("Work_select3", "3轮工况", bit6, getValue("0x0101_2", bit6)));
                dataList.add(new ObdFrameItem("Work_select4", "4轮工况", bit7, getValue("0x0101_2", bit7)));
            }
            //1字节
            else if (i == 1) {
                dataList.add(new ObdFrameItem("Work_mode", "工作模式", bit0, getValue("0x0101_3", bit0)));
                dataList.add(new ObdFrameItem("Control_mode", "控制模式", bit1, getValue("0x0101_4", bit1)));
                dataList.add(new ObdFrameItem("bParallel_status", "并轮状态", bit2, getValue("0x0101_5", bit2)));
                dataList.add(new ObdFrameItem("dir_pos", "手柄方向", bit3, getValue("0x0101_6", bit3)));
                dataList.add(new ObdFrameItem("dir_pos1", "手柄方向", bit4, getValue("0x0101_7", bit4)));
                dataList.add(new ObdFrameItem("Fan_IN", "风扇开关", bit5, getValue("0x0101_11", bit5)));
                dataList.add(new ObdFrameItem("Fan_WORK", "风扇状态", bit6, getValue("0x0101_9", bit6)));
                dataList.add(new ObdFrameItem("Status.clamp", "钢丝绳夹紧", bit7, getValue("0x0101_7", bit7)));
            }
            //2字节
            else if (i == 2) {
                dataList.add(new ObdFrameItem("count_set1", "计数状态1", bit0, getValue("0x0101_8", bit0)));
                dataList.add(new ObdFrameItem("count_set2", "计数状态2", bit1, getValue("0x0101_8", bit1)));
                dataList.add(new ObdFrameItem("count_set3", "计数状态3", bit2, getValue("0x0101_8", bit2)));
                dataList.add(new ObdFrameItem("count_set4", "计数状态4", bit3, getValue("0x0101_8", bit3)));
                dataList.add(new ObdFrameItem("bWinch1_clamp", "夹紧装置1", bit4, getValue("0x0101_7", bit4)));
                dataList.add(new ObdFrameItem("bWinch2_clamp", "夹紧装置2", bit5, getValue("0x0101_7", bit5)));
                dataList.add(new ObdFrameItem("bWinch3_clamp", "夹紧装置3", bit6, getValue("0x0101_7", bit6)));
                dataList.add(new ObdFrameItem("bWinch4_clamp", "夹紧装置4", bit7, getValue("0x0101_7", bit7)));
            }
            //3字节
            else if (i == 3) {
                dataList.add(new ObdFrameItem("sErro.press_highsensor1", "主泵压力传感器1", bit0, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.press_highsensor2", "主泵压力传感器2", bit1, getValue("0x0101_9", bit1)));
                dataList.add(new ObdFrameItem("sErro.press_mainsensor1", "主压力传感器1", bit2, getValue("0x0101_9", bit2)));
                dataList.add(new ObdFrameItem("sErro.press_mainsensor2", "主压力传感器2", bit3, getValue("0x0101_9", bit3)));
                dataList.add(new ObdFrameItem("sErro.press_mainsensor3", "主压力传感器3", bit4, getValue("0x0101_9", bit4)));
                dataList.add(new ObdFrameItem("sErro.press_mainsensor4", "主压力传感器4", bit5, getValue("0x0101_9", bit5)));
                dataList.add(new ObdFrameItem("sErro.boostpresssensor", "补油压力传感器", bit6, getValue("0x0101_9", bit6)));
                dataList.add(new ObdFrameItem("sErro.auxpresssensor", "尾架压力传感器", bit7, getValue("0x0101_9", bit7)));
            }
            //4字节
            else if (i == 4) {
                dataList.add(new ObdFrameItem("sErro.brake1", "1轮制动电磁铁", bit0, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.brake2", "2轮制动电磁铁", bit1, getValue("0x0101_9", bit1)));
                dataList.add(new ObdFrameItem("sErro.brake3", "3轮制动电磁铁", bit2, getValue("0x0101_9", bit2)));
                dataList.add(new ObdFrameItem("sErro.brake4", "4轮制动电磁铁", bit3, getValue("0x0101_9", bit3)));
                dataList.add(new ObdFrameItem("sErro.joyst", "控制手柄", bit4, getValue("0x0101_9", bit4)));
                dataList.add(new ObdFrameItem("sErro.remote_can_join", "远程CAN联结", bit5, getValue("0x0101_9", bit5)));
                dataList.add(new ObdFrameItem("sErro.boostpress", "补油压力报警", bit6, getValue("0x0101_12", bit6)));
                dataList.add(new ObdFrameItem("sErro.auxpress", "尾架压力报警", bit7, getValue("0x0101_12", bit7)));
            }
            //5字节
            else if (i == 5) {
                dataList.add(new ObdFrameItem("sErro.vp1", "系统电压报警", bit0, getValue("0x0101_12", bit0)));
                dataList.add(new ObdFrameItem("sErro.Oil_press", "机油压力报警", bit1, getValue("0x0101_12", bit1)));
                dataList.add(new ObdFrameItem("sErro.oiltemp", "液压油温度报警", bit2, getValue("0x0101_12", bit2)));
                dataList.add(new ObdFrameItem("sErro.Suck_alarm", "吸油滤油器报警", bit3, getValue("0x0101_12", bit3)));
                dataList.add(new ObdFrameItem("sErro.Back_alarm", "回油滤油器报警", bit4, getValue("0x0101_12", bit4)));
                dataList.add(new ObdFrameItem("sErro_fuellevel", "燃油不足报警", bit5, getValue("0x0101_12", bit5)));
                dataList.add(new ObdFrameItem("sErro.watertemp", "柴油机水温报警", bit6, getValue("0x0101_12", bit6)));
                dataList.add(new ObdFrameItem("status.BX", "摆线状态", bit7, getValue("0x0101_10", bit7)));
            }
            //6字节
            else if (i == 6) {
                dataList.add(new ObdFrameItem("sErro.pos_cur1", "牵引电磁铁故障", bit0, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.neu_cur1", "送线电磁铁故障", bit1, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.main_cur1", "主电磁铁1故障", bit2, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.main_cur2", "主电磁铁2故障", bit3, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.struc_cur1", "尾架电磁铁故障", bit4, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.fan_cur1", "风扇电磁铁故障", bit5, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.main_cur3", "主电磁铁3故障", bit6, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.main_cur4", "主电磁铁4故障", bit7, getValue("0x0101_9", bit0)));
            }
            //7字节
            else if (i == 7) {
                dataList.add(new ObdFrameItem("sErro.select1", "牵引选择电磁铁1故障", bit0, getValue("0x0101_9", bit0)));
                dataList.add(new ObdFrameItem("sErro.select2", "牵引选择电磁铁2故障", bit1, getValue("0x0101_9", bit1)));
                dataList.add(new ObdFrameItem("sErro.select3", "牵引选择电磁铁3故障", bit2, getValue("0x0101_9", bit2)));
                dataList.add(new ObdFrameItem("sErro.select4", "牵引选择电磁铁4故障", bit3, getValue("0x0101_9", bit3)));
                dataList.add(new ObdFrameItem("sErro.fan_select", "风扇选择电磁铁故障", bit4, getValue("0x0101_9", bit4)));
                dataList.add(new ObdFrameItem("sErro.bParallel", "并轮选择电磁铁故障", bit5, getValue("0x0101_9", bit5)));
                dataList.add(new ObdFrameItem("sErro.bswl", "摆线电磁铁1故障", bit6, getValue("0x0101_9", bit6)));
                dataList.add(new ObdFrameItem("sErro.bsw2", "摆线电磁铁2故障", bit7, getValue("0x0101_9", bit7)));
            }
        }
        return dataList;
    }

    /**
     * 解析数据(frameId=0x0111)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData111(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("tension1_set", "预置张力1", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1));
        ObdFrameItem item2 = new ObdFrameItem("tension1", "主张力1", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]) * 0.1));
        ObdFrameItem item3 = new ObdFrameItem("tension2_set", "预置张力2", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]) * 0.1));
        ObdFrameItem item4 = new ObdFrameItem("tension2", "主张力2", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]) * 0.1));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0112)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData112(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("tension3_set", "预置张力3", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1));
        ObdFrameItem item2 = new ObdFrameItem("tension3", "主张力3", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]) * 0.1));
        ObdFrameItem item3 = new ObdFrameItem("tension4_set", "预置张力4", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]) * 0.1));
        ObdFrameItem item4 = new ObdFrameItem("tension4", "主张力4", "kN", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]) * 0.1));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0113)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData113(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("force1", "牵引力", "kN", round(ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1, 3));
        ObdFrameItem item2 = new ObdFrameItem("force_set1", "预置牵引力", "kN", round(ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]) * 0.1, 3));
        ObdFrameItem item3 = new ObdFrameItem("speed1", "1轮速度", "km/h", round(ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]) * 0.1, 3));
        ObdFrameItem item4 = new ObdFrameItem("length1", "1轮放线里程", "m", round(ByteUtil.getSignedShort(frameData[6], frameData[7]), 3));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0114)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData114(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("speed2", "2轮速度", "km/h", round(ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1, 3));
        ObdFrameItem item2 = new ObdFrameItem("length2", "2轮放线里程", "m", round(ByteUtil.getSignedShort(frameData[2], frameData[3]), 3));
        ObdFrameItem item3 = new ObdFrameItem("speed3", "3轮速度", "km/h", round(ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]) * 0.1, 3));
        ObdFrameItem item4 = new ObdFrameItem("length3", "3轮放线里程", "m", round(ByteUtil.getSignedShort(frameData[6], frameData[7]), 3));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0115)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData115(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("speed4", "4轮速度", "km/h", round(ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1, 3));
        ObdFrameItem item2 = new ObdFrameItem("length4", "4轮放线里程", "m", round(ByteUtil.getSignedShort(frameData[2], frameData[3]), 3));
        ObdFrameItem item3 = new ObdFrameItem("joyst", "手柄位置", "%", round(ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]), 3));
        ObdFrameItem item4 = new ObdFrameItem("pedal", "踏板位置", "%", round(ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]), 3));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0116)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData116(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("speed_set", "预置牵引速度", "km/h", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(frameId=0x0120)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData120(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("total_length1", "放线总里程1", "m", ByteUtil.low4ByteToLongBE(frameData[0], frameData[1], frameData[2], frameData[3]));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(frameId=0x0121)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData121(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("total_length2", "放线总里程2", "m", ByteUtil.low4ByteToLongBE(frameData[0], frameData[1], frameData[2], frameData[3]));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(frameId=0x0131)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData131(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");

        ObdFrameItem item1 = new ObdFrameItem("ubat_supply", "系统电压", "V", round(ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]) * 0.1, 3));
        ObdFrameItem item2 = new ObdFrameItem("oil_tem", "液压油温度", "℃", round(ByteUtil.getSignedShort(frameData[2], frameData[3]), 1));
        ObdFrameItem item3 = new ObdFrameItem("fuel_level", "柴油油位", "%", ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]));
        return Arrays.asList(item1, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0132)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData132(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("pump1_pressure", "主泵1压力", "bar", ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]));
        ObdFrameItem item2 = new ObdFrameItem("pump2_pressure", "主泵2压力", "bar", ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]));
        ObdFrameItem item3 = new ObdFrameItem("main_pressue1", "主压力1", "bar", ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]));
        ObdFrameItem item4 = new ObdFrameItem("main_pressue2", "主压力2", "bar", ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0133)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData133(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("main_pressue3", "主压力3", "bar", ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]));
        ObdFrameItem item2 = new ObdFrameItem("main_pressue4", "主压力4", "bar", ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]));
        ObdFrameItem item3 = new ObdFrameItem("aux_pressue", "辅助压力", "bar", ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]));
        ObdFrameItem item4 = new ObdFrameItem("boost_pressure", "补油压力", "bar", ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0134)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData134(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("pos_cur1", "牵引电流1", "mA", round(ByteUtil.getSignedShort(frameData[0], frameData[1]) * 0.1, 1));
        ObdFrameItem item2 = new ObdFrameItem("neu_cur1", "送线电流1", "mA", round(ByteUtil.getSignedShort(frameData[2], frameData[3]) * 0.1, 1));
        ObdFrameItem item3 = new ObdFrameItem("pos_cur2", "牵引电流2", "mA", round(ByteUtil.getSignedShort(frameData[4], frameData[5]) * 0.1, 1));
        ObdFrameItem item4 = new ObdFrameItem("neu_cur2", "送线电流2", "mA", round(ByteUtil.getSignedShort(frameData[6], frameData[7]) * 0.1, 1));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0135)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData135(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("main_cur1", "控制电流1", "mA", round(ByteUtil.getSignedShort(frameData[0], frameData[1]) * 0.1, 1));
        ObdFrameItem item2 = new ObdFrameItem("main_cur2", "控制电流2", "mA", round(ByteUtil.getSignedShort(frameData[2], frameData[3]) * 0.1, 1));
        ObdFrameItem item3 = new ObdFrameItem("main_cur3", "控制电流3", "mA", round(ByteUtil.getSignedShort(frameData[4], frameData[5]) * 0.1, 1));
        ObdFrameItem item4 = new ObdFrameItem("main_cur4", "控制电流4", "mA", round(ByteUtil.getSignedShort(frameData[6], frameData[7]) * 0.1, 1));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0136)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData136(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("aux_cur", "辅助电流", "mA", round(ByteUtil.getSignedShort(frameData[0], frameData[1]) * 0.1, 1));
        ObdFrameItem item2 = new ObdFrameItem("fan_cur", "风扇电流", "mA", round(ByteUtil.getSignedShort(frameData[2], frameData[3]) * 0.1, 1));
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(frameId=0x0151)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData151(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("total_engine_hours", "工作时间", "h", ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]));
        ObdFrameItem item2 = new ObdFrameItem("engine_speed", "柴油机转速", "rpm", ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]));
        ObdFrameItem item3 = new ObdFrameItem("engine_oil_pressure", "机油压力", "kpa", ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]));
        ObdFrameItem item4 = new ObdFrameItem("engine_coolant_temperature", "柴油机水温", "℃", ByteUtil.getSignedShort(frameData[6], frameData[7]));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x0152)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData152(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("engine_oil_temperature", "机油温度", "℃", round(ByteUtil.getSignedShort(frameData[0], frameData[1]), 1));
        ObdFrameItem item2 = new ObdFrameItem("total_fuel_consumption", "总油耗", "L", round(ByteUtil.low4ByteToLongBE(frameData[4], frameData[5], frameData[6], frameData[7]), 3));
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(frameId=0x0153)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData153(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        //ObdFrameItem item1 = new ObdFrameItem("water_temp", "柴油机水温", "℃", round(ByteUtil.getSignedShort(frameData[0], frameData[1]), 1));
        //ObdFrameItem item2 = new ObdFrameItem("oil_pressure", "机油压力", "bar", round(ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]) * 0.1, 1));
        return Arrays.asList();
    }

    /**
     * 解析数据(frameId=0x0CF00400)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0CF00400(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");

        int value0 = (0x0f & frameData[0]);
        int byte45 = ByteUtil.low2ByteToIntBE(frameData[3], frameData[4]);

        ObdFrameItem item1 = new ObdFrameItem("engine_torque_mode", "发动机扭矩模式", value0, ENGINE_TORQUE_MODE[value0]);
        ObdFrameItem item2 = new ObdFrameItem("driver_engine_percent_torque", "驾驶指令百分比扭矩", "%", frameData[1] - 125);
        ObdFrameItem item3 = new ObdFrameItem("actual_engine_percent_torque", "发动机实际扭矩百分比", "%", frameData[2] - 125);
        ObdFrameItem item4 = new ObdFrameItem("engine_speed", "发动机速度", "rpm", round(byte45 * 0.125, 3));
        ObdFrameItem item5 = new ObdFrameItem("source_address_engine_control", "控制发动机设备源地址", frameData[5], String.valueOf(frameData[5]));
        //第7个字节not used
        ObdFrameItem item6 = new ObdFrameItem("engine_demand_percent_torque", "发动机需求扭矩百分比", "%", frameData[7] - 125);
        return Arrays.asList(item1, item2, item3, item4, item5, item6);
    }

    /**
     * 解析数据(frameId=0x0CF00300)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0CF00300(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int data = frameData[0];
        //第1个字节
        int bit1 = ByteUtil.getBit(data, 0, 1);
        int bit2 = ByteUtil.getBit(data, 2, 3);
        int bit3 = ByteUtil.getBit(data, 4, 5);
        ObdFrameItem dataItem1 = new ObdFrameItem("accelerator_pedal_low_idle_switch", "加速踏板低怠速开关", bit1, getValue("0x0CF00300_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("accelerator_pedal_kick-down_switch", "踏板开关", bit2, getValue("0x0CF00300_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("road_speed_limit_status", "速度限制状态", bit3, getValue("0x0CF00300_3", bit2));
        //第2个字节
        ObdFrameItem item2 = new ObdFrameItem("accelerator_pedal_position", "踏板位置", "%", formattingNumbers(3, frameData[1] * 0.4));
        //第3个字节
        ObdFrameItem item3 = new ObdFrameItem("percent_load_at_current_speed", "当前转速下负荷百分比 ", "%", frameData[2]);
        //第4个字节
        ObdFrameItem item4 = new ObdFrameItem("remote_accelerator_pedal_position", "遥控油门踏板位置", "%", frameData[3]);
        //第5个字节not used
        //第6个字节not used
        //第7个字节
        ObdFrameItem item5 = new ObdFrameItem("actual_maximum_available_engine_ercentage_torque", "实际最大可用发动机耗油量转矩", "%", formattingNumbers(3, frameData[6] * 0.4));
        //第8个字节not used
        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3, item4, item5);
    }

    /**
     * 解析数据(frameId=0x18FEDF00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEDF00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte23 = ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]);
        ObdFrameItem item1 = new ObdFrameItem("nominal_friction_percent_torque", "摩擦扭矩百分比", "%", frameData[0] - 125);
        ObdFrameItem item2 = new ObdFrameItem("engine_desired_operating_speed", "发动机目标运行速度", "rpm", formattingNumbers(3, byte23 * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("engine_operating_speed_asymmetry_adjustment", "发动机目标运行速度", "ratio", frameData[3]);
        ObdFrameItem item4 = new ObdFrameItem("estimated_engine_parasitic_losses_percentTorque", "估计发动机损失-百分比", "%", frameData[4]);
        //第6个字节not used
        //第7个字节not used
        int data34 = ByteUtil.getBit(frameData[5], 2, 3);
        ObdFrameItem item5 = new ObdFrameItem("after_treatment_exhaust_dew_point_message_exhaust_bank_1", "处理后排气露点消息-排气库1", data34, getValue("0x18FEDF00_1", data34));
        return Arrays.asList(item1, item2, item3, item4, item5);
    }

    /**
     * 解析数据(AMBCON环境条件,frameId=0x18FEF500)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF500(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte1 = frameData[0];
        int byte23 = ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]);
        int byte45 = ByteUtil.low2ByteToIntBE(frameData[3], frameData[4]);
        int byte6 = frameData[5];
        int byte78 = ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]);
        ObdFrameItem item1 = new ObdFrameItem("barometric_pressure", "大气压力", "kPa", round(byte1 * 0.5, 3));
        ObdFrameItem item2 = new ObdFrameItem("cab_interior_temperature", "发动机舱内部温度", byte23, "不可用");
        if (0xFFFF != byte23) {
            item2 = new ObdFrameItem("cab_interior_temperature", "发动机舱内部温度", "℃", byte23);
        }
        ObdFrameItem item3 = new ObdFrameItem("ambient_air_temperature", "大气温度", "℃", round(byte45 * 0.03125 - 273, 3));
        ObdFrameItem item4 = new ObdFrameItem("air_inlet_temperature", "进气温度", "℃", byte6 - 40);
        ObdFrameItem item5 = new ObdFrameItem("road_surface_temperature", "路面温度", byte78, "不可用");
        if (0xFFFF != byte78) {
            item5 = new ObdFrameItem("road_surface_temperature", "路面温度", "℃", byte78);
        }
        return Arrays.asList(item1, item2, item3, item4, item5);
    }

    /**
     * 解析数据(CrCtlVehSpd巡航控制,frameId=0x18FEF100)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF100(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int data = frameData[0];
        int byte23 = ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]);
        int bit1 = ByteUtil.getBit(data, 2, 3);
        ObdFrameItem item1 = new ObdFrameItem("status_of_parking_brake", "刹车开关状态", bit1, getValue("0x18FEF100_1", bit1));

        ObdFrameItem item2 = new ObdFrameItem("wheel_based_vehicle_speed", "车速", "km/h", byte23 * 256);

        int byte4 = frameData[3];
        int bit2 = ByteUtil.getBit(byte4, 6, 7);
        int bit3 = ByteUtil.getBit(byte4, 4, 5);
        int bit4 = ByteUtil.getBit(byte4, 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("status_of_clutch_switch", "离合开关状态", bit2, getValue("0x18FEF100_1", bit2));

        ObdFrameItem dataItem2 = new ObdFrameItem("status_of_brake_switch", "刹车开关状态", bit3, getValue("0x18FEF100_1", bit3));

        ObdFrameItem dataItem3 = new ObdFrameItem("cruise_control_active", "巡航控制激活状态标识", bit4, getValue("0x18FEF100_2", bit4));

        int byte5 = frameData[4];
        int bit5 = ByteUtil.getBit(byte5, 6, 7);
        int bit6 = ByteUtil.getBit(byte5, 4, 5);
        int bit7 = ByteUtil.getBit(byte5, 2, 3);
        int bit8 = ByteUtil.getBit(byte5, 0, 1);
        ObdFrameItem dataItem4 = new ObdFrameItem("cruise_control_accelerate_switch", "巡航控制加速开关", bit5, getValue("0x18FEF100_2", bit5));

        ObdFrameItem dataItem5 = new ObdFrameItem("cruise_control_resume_switch ", "巡航控制恢复开关", bit6, getValue("0x18FEF100_2", bit6));

        ObdFrameItem dataItem6 = new ObdFrameItem("cruise_control_coast _decelerate_switch ", "巡航按键减", bit7, getValue("0x18FEF100_2", bit7));

        ObdFrameItem dataItem7 = new ObdFrameItem("cruise_control_set_switch  ", "巡航控制开关", bit8, getValue("0x18FEF100_2", bit8));

        ObdFrameItem item3 = new ObdFrameItem("cruise_control_set_speed", "巡航控制设定速度", "km/h", frameData[5]);

        int byte6 = frameData[6];
        int bit9 = ByteUtil.getBit(byte6, 5, 7);
        int bit10 = ByteUtil.getBit(byte6, 0, 4);
        ObdFrameItem dataItem8 = new ObdFrameItem("cruise_control_state", "巡航控制状态", bit9, getValue("0x18FEF100_3", bit9));

        ObdFrameItem dataItem9 = new ObdFrameItem("PTO_state", "PTO状态", bit10, getValue("0x18FEF100_4", bit10));
        return Arrays.asList(item1, item2, dataItem1, dataItem2, dataItem3, dataItem4, dataItem5, dataItem6, dataItem7, dataItem8, dataItem9, item3);
    }


    /**
     * 解析数据(DM1/DM2 (SINGLE)frameId=0x18FECA00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FECA00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit178 = ByteUtil.getBit(frameData[0], 6, 7);
        int bit156 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit134 = ByteUtil.getBit(frameData[0], 2, 3);
        //int bit112 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("MIL", "MIL灯状态", bit178, getValue("0x18FECA00_1", bit178));
        ObdFrameItem dataItem2 = new ObdFrameItem("RSL", "红色停止灯状态", bit156, getValue("0x18FECA00_2", bit156));
        ObdFrameItem dataItem3 = new ObdFrameItem("AWL", "环境警告灯（闪码灯）状态", bit134, getValue("0x18FECA00_2", bit134));
        //ObdFrameItem dataItem4 = new ObdFrameItem("PL", "保护灯状态", bit112, getValue("0x18FECA00_2", bit112));

        ObdDtc dtc = parseObdDtc(frameData[2], frameData[3], frameData[4], frameData[5]);
        ObdFrameItem item1 = new ObdFrameItem("dtc", "诊断故障代码", dtc, "");
        return Arrays.asList(dataItem1, dataItem2, dataItem3, item1);
    }

    /**
     * 解析数据(DM1/DM2 BAM当前/历史故障信息通告,frameId=0x18ECFF00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18ECFF00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte1 = frameData[0];
        int byte23 = ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]);
        int byte4 = frameData[3];
        String pgn = ByteUtil.toHexString(frameData[5]) + ByteUtil.toHexString(frameData[6]) + ByteUtil.toHexString(frameData[7]);
        ObdFrameItem item1 = new ObdFrameItem("control_byte", "控制字节", byte1, "");
        ObdFrameItem item2 = new ObdFrameItem("total_bytes", "总信息字节数", byte23, "");
        ObdFrameItem item3 = new ObdFrameItem("total_packets", "总包数", byte4, "");
        ObdFrameItem item4 = new ObdFrameItem("PGN", "PGN", (Object) pgn, "");
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(DM1/DM2 PACK,frameId=0x18EBFF00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18EBFF00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int packet1Id = frameData[0];
        if (packet1Id == DTC_PACKET_1) {
            ObdDtc dtc1 = parseObdDtc(frameData[3], frameData[4], frameData[5], frameData[6]);
            ObdFrameItem item1 = new ObdFrameItem("diagnostic_lamp", "诊断灯", frameData[1], "");
            ObdFrameItem item2 = new ObdFrameItem("dtc", "诊断故障代码1", dtc1, "");
            return Arrays.asList(item1, item2);
        }
        if (packet1Id == DTC_PACKET_2) {
            ObdDtc dtc3 = parseObdDtc(frameData[4], frameData[5], frameData[6], frameData[7]);
            ObdFrameItem item4 = new ObdFrameItem("dtc", "诊断故障代码3", dtc3, "");
            return Arrays.asList(item4);
        }
        if (packet1Id == DTC_PACKET_3) {
            ObdDtc dtc4 = parseObdDtc(frameData[1], frameData[2], frameData[3], frameData[4]);
            ObdFrameItem item5 = new ObdFrameItem("dtc", "诊断故障代码4", dtc4, "");
            return Arrays.asList(item5);
        }
        return Collections.emptyList();
    }


    /**
     * 解析数据(EngTemp发动机温度,frameId=0x18FEEE00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEEE00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte1 = frameData[0];
        int byte2 = frameData[1];
        int byte34 = ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]);
        ObdFrameItem item1 = new ObdFrameItem("engine_coolant_temperature", "发动机冷却水温度", "℃", byte1 - 40);
        ObdFrameItem item2 = new ObdFrameItem("fuel_temperature", "燃油温度", "℃", byte2 - 40);
        ObdFrameItem item3 = new ObdFrameItem("engine_oil_temperature", "机油温度", "℃", round(byte34 * 0.03125 - 273, 2));
        return Arrays.asList(item1, item2, item3);
    }

    /**
     * 解析数据(FlCo燃油经济性,frameId=0x18FEF200)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF200(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte1_2 = ByteUtil.low2ByteToIntBE(frameData[0], frameData[1]);
        int byte3_4 = ByteUtil.low2ByteToIntBE(frameData[2], frameData[3]);
        ObdFrameItem item1 = new ObdFrameItem("fuel_rate", "油耗", "L/h", round(byte1_2 * 0.05, 3));
        ObdFrameItem item2 = new ObdFrameItem("instantaneous_fuel_economy", "瞬时油耗", "Km/L", round(byte3_4 * 0.001953125, 5));
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(EFL/P1发动机液位/压力,frameId=0x18FEEF00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEEF00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte3 = frameData[2];
        int byte4 = frameData[3];
        ObdFrameItem item1 = new ObdFrameItem("engine_oil_level", "机油液位", "%", round(byte3 * 0.4, 3));
        ObdFrameItem item2 = new ObdFrameItem("engine_oil_pressure", "机油压力", "kPa", byte4 * 4);
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(FlCo燃油消耗量,frameId=0x18FEE900)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEE900(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        long byte1_4 = ByteUtil.low4ByteToLongBE(frameData[0], frameData[1], frameData[2], frameData[3]);
        long byte5_8 = ByteUtil.low4ByteToLongBE(frameData[4], frameData[5], frameData[6], frameData[7]);
        ObdFrameItem item1 = new ObdFrameItem("trip_fuel_consumption", "里程油耗", "L", byte1_4 * 0.5);
        ObdFrameItem item2 = new ObdFrameItem("total_fuel_consumption", "总油耗", "L", byte5_8 * 0.5);
        return Arrays.asList(item1, item2);
    }


    /**
     * 解析数据(INCON发动机进气条件,frameId=0x18FEF600)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF600(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte2 = frameData[1];
        int byte3 = frameData[2];
        int byte4 = frameData[3];
        int byte6_7 = ByteUtil.low2ByteToIntBE(frameData[5], frameData[6]);
        ObdFrameItem item1 = new ObdFrameItem("boost_pressure_atmosphere pressure", "相对增压压力", "kPa", byte2 * 2);
        ObdFrameItem item2 = new ObdFrameItem("intake_manifold_temperature", "进气温度", "℃", byte3 - 40);
        ObdFrameItem item3 = new ObdFrameItem("absolute_boost_pressure", "绝对增压压力", "kPa", byte4 * 2);
        ObdFrameItem item4 = new ObdFrameItem("exhaust_gas_temperature", "排气温度", "℃", round(byte6_7 * 0.03125, 3));
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(VehPow整车电源,frameId=0x18FEF700)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF700(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int byte7_8 = ByteUtil.low2ByteToIntBE(frameData[6], frameData[7]);
        ObdFrameItem item1 = new ObdFrameItem("battery_voltage ", "电瓶电压", "V", round(byte7_8 * 0.05, 3));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(EngHrRev发动机运行时间,frameId=0x18FEE500)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEE500(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        long byte1_4 = ByteUtil.low4ByteToLongBE(frameData[0], frameData[1], frameData[2], frameData[3]);
        ObdFrameItem item1 = new ObdFrameItem("total_engine_hours", "总运行时长", "h", round(byte1_4 * 0.05, 2));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(frameId=0x18FEE400)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEE400(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[3], 0, 1);
        int bit2 = ByteUtil.getBit(frameData[4], 0, 1);
        ObdFrameItem item1 = new ObdFrameItem("engine_wait_to_start_lamp", "进气加热指示灯状态", bit1, getValue("0x18FEE400_1", bit1));

        ObdFrameItem item2 = new ObdFrameItem("engine_protection_system_has_shutdown_engine", "发动机保护系统已关闭发动机", bit2, getValue("0x18FEE400_1", bit2));
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(frameId=0x18FEBD00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEBD00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[1], 0, 3);
        ObdFrameItem item1 = new ObdFrameItem("estimated_percent_fan_speed", "估计风扇转速百分比", "%", formattingNumbers(3, frameData[0] * 0.4));
        ObdFrameItem item2 = new ObdFrameItem("fan_drive_state", "风扇驱动状态", bit1, getValue("0x18FEBD00_1", bit1));
        ObdFrameItem item3 = new ObdFrameItem("fan_Speed", "风扇转速", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[3], frameData[4]) * 0.125));
        return Arrays.asList(item1, item2, item3);
    }

    /**
     * 解析数据(frameId=0x18FEE000)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEE000(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("trip_distance ", "往返距离", "Km", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[0], frameData[1], frameData[2], frameData[3]) * 0.125));
        ObdFrameItem item2 = new ObdFrameItem("vehicle_distance", "车辆的距离", "Km", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[4], frameData[5], frameData[6], frameData[7]) * 0.125));
        return Arrays.asList(item1, item2);
    }

    /**
     * 解析数据(frameId=0x18FF0800)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FF0800(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("relative_engine_oil_pressure", "相对机油压力", "kPa", frameData[0] * 4);
        int bit1 = ByteUtil.getBit(frameData[1], 0);
        int bit2 = ByteUtil.getBit(frameData[1], 1);
        int bit3 = ByteUtil.getBit(frameData[1], 2, 3);
        int bit4 = ByteUtil.getBit(frameData[1], 4, 5);
        int bit5 = ByteUtil.getBit(frameData[1], 6, 7);
        int bit6 = ByteUtil.getBit(frameData[2], 0);
        int bit7 = ByteUtil.getBit(frameData[2], 1);
        int bit8 = ByteUtil.getBit(frameData[2], 2);
        int bit9 = ByteUtil.getBit(frameData[2], 3);

        ObdFrameItem dataItem1 = new ObdFrameItem("the_target_GPS_lock_status", "目标GPS锁定状态", bit1, getValue("0x18FF0800_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("emergency_unlock_status", "紧急解锁状态", bit2, getValue("0x18FF0800_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("shift_to_remind", "换挡提醒", bit3, getValue("0x18FF0800_3", bit3));
        ObdFrameItem dataItem4 = new ObdFrameItem("over_coolant_temperature_status", "过冷却剂温度状态", bit4, getValue("0x18FF0800_4", bit4));
        ObdFrameItem dataItem5 = new ObdFrameItem("engine_oil_pressure_status", "发动机机油压力状态", bit5, getValue("0x18FF0800_5", bit5));
        ObdFrameItem dataItem6 = new ObdFrameItem("GPS_lock_switch ", "目标GPS锁定开关", bit6, getValue("0x18FF0800_6", bit6));
        ObdFrameItem dataItem7 = new ObdFrameItem("GPS_lock_status", "目标GPS锁定状态", bit7, getValue("0x18FF0800_7", bit7));
        ObdFrameItem dataItem8 = new ObdFrameItem("the_key_test_status", "秘钥测试状态", bit8, getValue("0x18FF0800_8", bit8));
        ObdFrameItem dataItem9 = new ObdFrameItem("the_ID_test_status ", "ID测试状态", bit9, getValue("0x18FF0800_9", bit9));
        int bit10 = ByteUtil.getBit(frameData[2], 4, 7);
        int bit11 = ByteUtil.getBit(frameData[3], 0, 1);
        int bit12 = ByteUtil.getBit(frameData[3], 6);
        int bit13 = ByteUtil.getBit(frameData[3], 7);
        ObdFrameItem dataItem10 = new ObdFrameItem("cold_start_heater_status ", "冷启动加热器状态", bit10, getValue("0x18FF0800_10", bit10));
        ObdFrameItem dataItem11 = new ObdFrameItem("OBD_Lamp_status ", "OBD灯专业", bit11, getValue("0x18FF0800_10", bit11));
        ObdFrameItem dataItem12 = new ObdFrameItem("status_of_engine_running_while_T15_ON ", "T15开启时发动机运行状态", bit12, getValue("0x18FF0800_12", bit12));
        ObdFrameItem dataItem13 = new ObdFrameItem("emergency_start_status ", "紧急启动状态", bit13, getValue("0x18FF0800_13", bit13));

        ObdFrameItem item2 = new ObdFrameItem("exhaust_flap_valve_output", "排气瓣阀输出", "%", formattingNumbers(3, frameData[4] * 0.4));
        ObdFrameItem item3 = new ObdFrameItem("GPS_status_pulse_single", "GPS状态(单脉冲)", frameData[4], getValue("0x18FF0800_14", frameData[4]));
        return Arrays.asList(item1, dataItem1, dataItem2, dataItem3, dataItem4, dataItem5, dataItem6, dataItem7, dataItem8, dataItem9, dataItem10, dataItem11, dataItem12, dataItem13, item2, item3);
    }

    /**
     * 解析数据(frameId=0x18FEFF00)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEFF00(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[1], 0, 1);
        ObdFrameItem item1 = new ObdFrameItem("water_in_fuel_indicator", "油中有水指示灯状态", bit1, getValue("0x18FEFF00_1", bit1));
        return Arrays.asList(item1);
    }

    /**
     * 解析数据(frameId=0x18F0010B)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18F0010B(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[1], 6, 7);
        int bit2 = ByteUtil.getBit(frameData[1], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[1], 0, 1);
        int bit4 = ByteUtil.getBit(frameData[3], 3, 4);
        int bit5 = ByteUtil.getBit(frameData[5], 6, 7);
        int bit6 = ByteUtil.getBit(frameData[5], 4, 5);
        int bit7 = ByteUtil.getBit(frameData[5], 2, 3);
        ObdFrameItem dataItem1 = new ObdFrameItem("EBS_brake_switch", "电子刹车系统开关", bit1, getValue("0x18F0010B_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("ASR_brake_control_active/ASR", "刹车控制激活", bit2, getValue("0x18F0010B_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("ASR_engine_control_active", "控制发动机状态激活", bit3, getValue("0x18F0010B_3", bit3));
        ObdFrameItem dataItem4 = new ObdFrameItem("auxiliary_engine_shut_down", "辅助发动机停机", bit4, getValue("0x18F0010B_4", bit4));
        // TODO: 2020/11/14 文档未定义
        ObdFrameItem dataItem5 = new ObdFrameItem("文档未定义", "文档未定义", bit5, getValue("0x18F0010B_5", bit5));
        ObdFrameItem dataItem6 = new ObdFrameItem("the_ABS/EBS_amber/yellow_optical_warning_signal", "ABS/EBS琥珀色/黄色光学警告信号", bit6, getValue("0x18F0010B_6", bit6));
        ObdFrameItem dataItem7 = new ObdFrameItem("EBS_red_optical_warning_signal", "EBS红色光学警告信号", bit7, getValue("0x18F0010B_7", bit7));
        return Arrays.asList(dataItem1, dataItem2, dataItem3, dataItem4, dataItem5, dataItem6, dataItem7);

    }

    /**
     * 解析数据(frameId=0x0CF00203)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0CF00203(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[0], 0, 1);
        int bit4 = ByteUtil.getBit(frameData[4], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("shift_in_process ", "换挡过程", bit1, getValue("0x0CF00203_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("torque_converter_lockup_engaged ", "扭矩转换锁定/结合", bit2, getValue("0x0CF00203_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("driveline_engaged ", "动力传动系统进行", bit3, getValue("0x0CF00203_3", bit3));
        ObdFrameItem item2 = new ObdFrameItem("output_shaft_speed(gearbox_output_speed)", "输出轴转速(变速箱输出转速)", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("percent_clutch_slip", "百分比离合器滑", "%", formattingNumbers(3, frameData[3] * 0.4));
        // TODO: 2020/11/14 文档未定义
        ObdFrameItem dataItem4 = new ObdFrameItem("文档未定义 ", "文档未定义", bit4, getValue("0x0CF00203_4", bit4));
        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3, dataItem4);
    }

    /**
     * 解析数据(frameId=0x18F00503)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18F00503(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("selected_gear ", "选择齿轮", "gear", frameData[0] - 125);
        ObdFrameItem item2 = new ObdFrameItem("actual_gear_ratio_low_byte", "实际传动比低字节", "", formattingNumbers(3, frameData[1] * 0.001));
        ObdFrameItem item3 = new ObdFrameItem("actual_gear_ratio_high_byte ", "实际传动比高字节", "", formattingNumbers(3, frameData[2] * 0.001));
        ObdFrameItem item4 = new ObdFrameItem("current_gear ", "当前齿轮", "gear", frameData[0] - 125);
        return Arrays.asList(item1, item2, item3, item4);
    }

    /**
     * 解析数据(frameId=0x18FE4A03)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FE4A03(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[1], 4, 5);
        ObdFrameItem dataItem1 = new ObdFrameItem("transmission_engine_crank_enable", "变速箱发动机曲柄使能", bit1, getValue("0x18FE4A03_1", bit1));
        return Arrays.asList(dataItem1);
    }

    /**
     * 解析数据(frameId=0x18FEF121)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18FEF121(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit2 = ByteUtil.getBit(frameData[3], 6, 7);
        int bit3 = ByteUtil.getBit(frameData[3], 4, 5);
        int bit4 = ByteUtil.getBit(frameData[3], 0, 1);
        int bit5 = ByteUtil.getBit(frameData[4], 6, 7);
        int bit6 = ByteUtil.getBit(frameData[4], 4, 5);
        int bit7 = ByteUtil.getBit(frameData[4], 2, 3);
        int bit8 = ByteUtil.getBit(frameData[4], 0, 1);
        int bit9 = ByteUtil.getBit(frameData[4], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("status_of_parking_brake", "变速箱发动机曲柄使能", bit1, getValue("0x18FEF121_1", bit1));
        ObdFrameItem item1 = new ObdFrameItem("wheel_based_vehicle_speed", "车速", "Km/h", formattingNumbers(5, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.00390625));
        ObdFrameItem dataItem2 = new ObdFrameItem("status_of_clutch_switch", "离合开关状态", bit2, getValue("0x18FEF121_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("status_of_brake_switch", "刹车开关状态", bit3, getValue("0x18FEF121_3", bit3));
        ObdFrameItem dataItem4 = new ObdFrameItem("cruise_control_active_status", "巡航控制有效状态", "", bit4);
        ObdFrameItem dataItem5 = new ObdFrameItem("cruise_Control_acceleration_switch(SPN 602)", "巡航控制有效状态", "", bit5);
        ObdFrameItem dataItem6 = new ObdFrameItem("cruise_control_resume_switch(SPN 601)", "巡航控制恢复开关(SPN601)", "", bit6);
        ObdFrameItem dataItem7 = new ObdFrameItem("cruise_control_decelerate_switch(SPN 600)", "巡航控制减速开关(spn600)", "", bit7);
        ObdFrameItem dataItem8 = new ObdFrameItem("cruise_controlSet_switch(SPN 599)", "巡航控制开关(spn599)", "", bit8);
        ObdFrameItem dataItem9 = new ObdFrameItem("status_of_brake_switch", "刹车开关状态", bit9, getValue("0x18FEF121_4", bit9));
        return Arrays.asList(dataItem1, item1, dataItem2, dataItem3, dataItem4, dataItem5, dataItem6, dataItem7, dataItem8, dataItem9);
    }

    /**
     * 解析数据(frameId=0x0CFE6CEE)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0CFE6CEE(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("tachograph_output_shaft_speed ", "转速表输出", "5rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[4], frameData[5]) * 0.125));
        ObdFrameItem item2 = new ObdFrameItem("tachograph_vehicle_speed-LSB", "转速表车速低字节", "/km/h", formattingNumbers(5, frameData[6] * 0.00390625));
        ObdFrameItem item3 = new ObdFrameItem("tachograph_vehicle_speed-MSB-LSB", "转速表车速高字节", "/km/h", formattingNumbers(5, frameData[7] * 0.00390625));
        return Arrays.asList(item1, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0C00000B)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C00000B(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C00000B_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("requested_speed_control_conditions", "请求速度控制条件", bit2, getValue("0x0C00000B_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("override_control_modes ", "override控制模式", bit3, getValue("0x0C00000B_3", bit3));
        ObdFrameItem item2 = new ObdFrameItem("requested_speed/speed_limit", " 目标转速/转速限制", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0C000F0B)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C000F0B(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C000F0B_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("override_control_modes ", "override控制模式", bit2, getValue("0x0C000F0B_2", bit2));
        ObdFrameItem item1 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, item1);
    }

    /**
     * 解析数据(frameId=0x0C000024)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C000024(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C000024_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("requested_speed_control_conditions", "请求速度控制条件", bit2, getValue("0x0C000024_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("override_control_modes ", "override控制模式", bit3, getValue("0x0C000024_1", bit3));

        ObdFrameItem item2 = new ObdFrameItem("requested_speed/speed_limit", " 目标转速/转速限制", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0C000021)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C000021(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C000021_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("requested_speed_control_conditions", "请求速度控制条件", bit2, getValue("0x0C000021_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("override_control_modes ", "override控制模式", bit3, getValue("0x0C000021_3", bit3));

        ObdFrameItem item2 = new ObdFrameItem("requested_speed/speed_limit", " 目标转速/转速限制", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0C000003)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C000003(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 2, 3);
        int bit3 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C000003_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("requested_speed_control_conditions", "请求速度控制条件", bit2, getValue("0x0C000003_2", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("override_control_modes ", "override控制模式", bit3, getValue("0x0C000003_1", bit3));

        ObdFrameItem item2 = new ObdFrameItem("requested_speed/speed_limit", " 目标转速/转速限制", "rpm", formattingNumbers(3, ByteUtil.low2ByteToIntBE(frameData[1], frameData[2]) * 0.125));
        ObdFrameItem item3 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, dataItem3, item2, item3);
    }

    /**
     * 解析数据(frameId=0x0C000F21)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0C000F21(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 4, 5);
        int bit2 = ByteUtil.getBit(frameData[0], 0, 1);
        ObdFrameItem dataItem1 = new ObdFrameItem("override_control_mode_priority ", "override控制模式优先级", bit1, getValue("0x0C000F21_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("override_control_modes ", "override控制模式", bit2, getValue("0x0C000F21_2", bit2));

        ObdFrameItem item1 = new ObdFrameItem("requested_torque/torque_limit", "目标扭矩/扭矩限制", "%", frameData[3] - 125);

        return Arrays.asList(dataItem1, dataItem2, item1);
    }

    /**
     * 解析数据(frameId=0x0CFF0431)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData0CFF0431(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        int bit1 = ByteUtil.getBit(frameData[0], 6, 7);
        int bit2 = ByteUtil.getBit(frameData[0], 6, 7);
        int bit3 = ByteUtil.getBit(frameData[1], 4, 5);
        int bit4 = ByteUtil.getBit(frameData[4], 2, 3);
        ObdFrameItem dataItem1 = new ObdFrameItem("T50_switch ", "T50 开关", bit1, getValue("0x0CFF0431_1", bit1));
        ObdFrameItem dataItem2 = new ObdFrameItem("engine_compartment_start_button", "车下启动", bit2, getValue("0x0CFF0431_1", bit2));
        ObdFrameItem dataItem3 = new ObdFrameItem("neutral_gear_position", "车下停止", bit3, getValue("0x0CFF0431_1", bit3));
        ObdFrameItem dataItem4 = new ObdFrameItem("engine_compartment_stop_button", "空档开关", bit4, getValue("0x0CFF0431_2", bit4));

        return Arrays.asList(dataItem1, dataItem2, dataItem3, dataItem4);
    }

    /**
     * 解析数据(frameId=0x18E00021)
     *
     * @param frameData
     * @return
     */
    public static List<ObdFrameItem> parseObdData18E00021(int[] frameData) {
        Preconditions.checkArgument(frameData.length >= 8, "数组长度不能小于8");
        ObdFrameItem item1 = new ObdFrameItem("requested_percent_fan_speed", "要求风扇转速百分比", "%", formattingNumbers(3, frameData[0] * 0.4));
        return Arrays.asList(item1);
    }


    /**
     * 解析dtc
     *
     * @param bytes 4字节
     * @return
     */
    public static ObdDtc parseObdDtc(int... bytes) {
        int byte1 = bytes[0];
        int byte2 = bytes[1];
        int byte3 = bytes[2];
        int byte4 = bytes[3];
        int spn = ByteUtil.low3ByteToIntBE(byte1, byte2, ByteUtil.getBit(byte3, 5, 7));
        int fmi = ByteUtil.getBit(byte3, 0, 4);
        int cm = ByteUtil.getBit(byte4, 7);
        int oc = ByteUtil.getBit(byte4, 0, 6);
        ObdDtc dtc = new ObdDtc();
        dtc.setSpn(spn);
        dtc.setFmi(fmi);
        dtc.setOc(oc);
        dtc.setCm(cm);
        return dtc;
    }

    /**
     * 解析故障诊断分包序号
     *
     * @param frameData
     * @return
     */
    public static int parseObdDmPacketNo(String frameData) {
        int[] bytes = translateFrameData(frameData);
        return bytes[0];
    }

    /**
     * 解析故障总包数
     *
     * @param frameData
     * @return
     */
    public static int parseTotalPackets(String frameData) {
        int[] bytes = translateFrameData(frameData);
        return bytes[3];
    }

    /**
     * 提取总油耗
     *
     * @param frameData
     * @return
     */
    public static double parseTotalFuelConsumption(String frameData) {
        List<ObdFrameItem> itemList = parseObdData(ID_18FEE900, frameData);
        for (ObdFrameItem item : itemList) {
            if (TOTAL_FUEL_CONSUMPTION.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取总油耗
     *
     * @param itemList
     * @return
     */
    public static double parseTotalFuelConsumption(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TOTAL_FUEL_CONSUMPTION.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取发动机转速
     *
     * @param itemList
     * @return
     */
    public static double parseEngineSpeed(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (ENGINE_SPEED.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取1轮张力
     *
     * @param itemList
     * @return
     */
    public static double parseTension1(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TENSION1.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取2轮张力
     *
     * @param itemList
     * @return
     */
    public static double parseTension2(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TENSION2.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取1轮速度
     *
     * @param itemList
     * @return
     */
    public static double parseSpeed1(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (SPEED1.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取2轮速度
     *
     * @param itemList
     * @return
     */
    public static double parseSpeed2(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (SPEED2.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取3轮速度
     *
     * @param itemList
     * @return
     */
    public static double parseSpeed3(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (SPEED3.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取4轮速度
     *
     * @param itemList
     * @return
     */
    public static double parseSpeed4(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (SPEED4.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取总放线里程1
     *
     * @param itemList
     * @return
     */
    public static long parseTotalLength1(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TOTAL_LENGTH1.equalsIgnoreCase(item.getCode())) {
                return Long.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取总放线里程2
     *
     * @param itemList
     * @return
     */
    public static long parseTotalLength2(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TOTAL_LENGTH2.equalsIgnoreCase(item.getCode())) {
                return Long.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 检测
     *
     * @param code
     * @param value
     * @return
     */
    public static boolean ObdData101IsError(String code, Integer value) {
        if (StringUtils.isNotBlank(code) && code.contains("sErro")) {
            if (value == 1) {
                return true;
            }
        }
        return false;
    }

    public static double parseTotalWorkHour(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (TOTAL_WORK_HOUR.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 提取牵引力
     *
     * @param itemList
     * @return
     */
    public static double parseForce(List<ObdFrameItem> itemList) {
        for (ObdFrameItem item : itemList) {
            if (FORCE.equalsIgnoreCase(item.getCode())) {
                return Double.valueOf(item.getValue().toString());
            }
        }
        return 0;
    }

    /**
     * 小数位格式化
     *
     * @param scale
     * @param numbers
     * @return
     */
    private static Double formattingNumbers(int scale, double numbers) {
        BigDecimal b = new BigDecimal(numbers);
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 数字取舍
     *
     * @param numbers
     * @param scale
     * @return
     */
    private static Double round(double numbers, int scale) {
        BigDecimal b = new BigDecimal(numbers);
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static void main(String[] args) {
        Long id = 419366912L;
        int[] data = translateFrameData("2d0080000000000f");
        parseObdData(id, data);
    }
}
